package com.huahai.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huahai.exception.BusinessException;
import com.huahai.exception.ErrorCode;
import com.huahai.mapper.BarrageMapper;
import com.huahai.pojo.dto.barrage.BarrageAddDTO;
import com.huahai.pojo.dto.barrage.BarrageQueryDTO;
import com.huahai.pojo.entity.Barrage;
import com.huahai.pojo.entity.User;
import com.huahai.pojo.vo.barrage.BarrageVO;
import com.huahai.pojo.vo.user.UserVO;
import com.huahai.service.BarrageService;
import com.huahai.service.UserService;
import com.huahai.util.ThrowUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author huahai
 * @description 针对表【barrage(弹幕)】的数据库操作Service实现
 * @createDate 2025-08-17 16:41:18
 */
@Service
public class BarrageServiceImpl extends ServiceImpl<BarrageMapper, Barrage> implements BarrageService {

    @Resource
    private UserService userService;

    /**
     * 给弹幕板添加弹幕
     * @param barrageAddDTO 弹幕添加参数
     * @param loginUser 登录用户
     * @return 添加的弹幕 id
     */
    @Override
    public Long addBarrage(BarrageAddDTO barrageAddDTO, User loginUser) {
        // 1. 校验参数
        ThrowUtils.throwIf(barrageAddDTO == null, ErrorCode.PARAMS_ERROR);
        Barrage barrage = new Barrage();
        BeanUtils.copyProperties(barrageAddDTO, barrage);
        validBarrage(barrage);
        // 2. 判断用户是否登录
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
        // 3. 补充参数，添加弹幕
        barrage.setUserId(loginUser.getId());
        boolean saveResult = this.save(barrage);
        ThrowUtils.throwIf(!saveResult, ErrorCode.OPERATION_ERROR);
        // 4. 返回添加的弹幕 id
        return barrage.getId();
    }

    /**
     * barrage 类型转换脱敏（单条弹幕）
     *
     * @param barrage 弹幕对象
     * @param request 请求
     * @return BarrageVO
     */
    @Override
    public BarrageVO getBarrageVO(Barrage barrage, HttpServletRequest request) {
        // 对象转封装类
        BarrageVO barrageVO = BarrageVO.objToVo(barrage);
        // 关联查询用户信息
        Long userId = barrage.getUserId();
        if (userId != null && userId > 0) {
            User user = userService.getById(userId);
            UserVO userVO = userService.getUserVO(user);
            barrageVO.setUser(userVO);
        }
        return barrageVO;
    }

    /**
     * 分页获取弹幕封装
     * @param barragePage 分页参数
     * @param request 请求
     * @return Page<SpaceVO> 分页后的脱敏弹幕列表
     */
    @Override
    public Page<BarrageVO> getBarrageVOPage(Page<Barrage> barragePage, HttpServletRequest request) {
        // 获取分页数据
        List<Barrage> barrageList = barragePage.getRecords();
        Page<BarrageVO> barrageVOPage = new Page<>(barragePage.getCurrent(), barragePage.getSize(), barragePage.getTotal());
        if (CollUtil.isEmpty(barrageList)) {
            return barrageVOPage;
        }
        // 对象列表 => 封装对象列表
        List<BarrageVO> barrageVOList = barrageList.stream().map(BarrageVO::objToVo).collect(Collectors.toList());
        // 1. 关联查询用户信息
        // 获取用户 id 列表
        Set<Long> userIdSet = barrageList.stream().map(Barrage::getUserId).collect(Collectors.toSet());
        Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
                .collect(Collectors.groupingBy(User::getId));
        // 2. 填充信息
        barrageVOList.forEach(barrageVO -> {
            Long userId = barrageVO.getUserId();
            User user = null;
            if (userIdUserListMap.containsKey(userId)) {
                user = userIdUserListMap.get(userId).get(0);
            }
            barrageVO.setUser(userService.getUserVO(user));
        });
        barrageVOPage.setRecords(barrageVOList);
        // 3. 返回数据
        return barrageVOPage;
    }

    /**
     * 封装弹幕查询条件 QueryWrapper
     *
     * @param barrageQueryDTO 弹幕查询条件
     * @return QueryWrapper<Barrage>
     */
    @Override
    public QueryWrapper<Barrage> getQueryWrapper(BarrageQueryDTO barrageQueryDTO) {
        QueryWrapper<Barrage> queryWrapper = new QueryWrapper<>();
        if (barrageQueryDTO == null) {
            return queryWrapper;
        }
        // 从对象中取值
        Long id = barrageQueryDTO.getId();
        Long userId = barrageQueryDTO.getUserId();
        String content = barrageQueryDTO.getContent();
        String sortField = barrageQueryDTO.getSortField();
        String sortOrder = barrageQueryDTO.getSortOrder();

        // 封装查询条件
        queryWrapper.eq(ObjUtil.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjUtil.isNotEmpty(userId), "userId", userId);
        queryWrapper.like(StrUtil.isNotBlank(content), "content", content);
        // 排序
        queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), sortOrder.equals("ascend"), sortField);
        return queryWrapper;
    }

    /**
     * 弹幕基本校验
     *
     * @param barrage 弹幕对象
     */
    @Override
    public void validBarrage(Barrage barrage) {
        // 校验参数
        if (barrage == null) {
            return;
        }
        String content = barrage.getContent();

        if (StrUtil.isBlank(content)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "内容不能为空");
        }

        if (content.length() > 32) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "内容过长");
        }
    }
}




